import * as R from 'ramda';
import { type FunctionComponent, useContext, useEffect, useState } from 'react';

import { deleteVulnerability, fetchVulnerability, updateVulnerability } from '../../../../actions/vulnerability-actions';
import ButtonPopover, { type PopoverEntry } from '../../../../components/common/ButtonPopover';
import DialogDelete from '../../../../components/common/DialogDelete';
import Drawer from '../../../../components/common/Drawer';
import { useFormatter } from '../../../../components/i18n';
import Loader from '../../../../components/Loader';
import { type VulnerabilityOutput, type VulnerabilitySimple, type VulnerabilityUpdateInput } from '../../../../utils/api-types';
import { MESSAGING$ } from '../../../../utils/Environment';
import { AbilityContext } from '../../../../utils/permissions/PermissionsProvider';
import { ACTIONS, SUBJECTS } from '../../../../utils/permissions/types';
import VulnerabilityForm from './VulnerabilityForm';

interface Props {
  onDelete?: (result: string) => void;
  onUpdate?: (result: VulnerabilitySimple) => void;
  vulnerability: VulnerabilitySimple;
}

const VulnerabilityPopover: FunctionComponent<Props> = ({ onDelete, onUpdate, vulnerability }) => {
  const { t } = useFormatter();
  const ability = useContext(AbilityContext);

  const [fullVulnerability, setFullVulnerability] = useState<VulnerabilityOutput | null>(null);
  const [loading, setLoading] = useState(false);

  const [openEdit, setOpenEdit] = useState(false);
  const [openDelete, setOpenDelete] = useState(false);

  const handleOpenEdit = () => setOpenEdit(true);
  const handleCloseEdit = () => {
    setOpenEdit(false);
    setFullVulnerability(null);
  };

  const handleOpenDelete = () => setOpenDelete(true);
  const handleCloseDelete = () => setOpenDelete(false);

  const handleDelete = () => {
    deleteVulnerability(vulnerability.vulnerability_id)
      .then(() => {
        onDelete?.(vulnerability.vulnerability_id);
      })
      .catch(() => {
        MESSAGING$.notifyError(t('Failed to delete vulnerability.'));
      })
      .finally(() => {
        handleCloseDelete();
      });
  };

  const handleSubmitEdit = (data: VulnerabilityUpdateInput) => {
    updateVulnerability(vulnerability.vulnerability_id, data)
      .then((response) => {
        onUpdate?.(response.data);
      })
      .catch(() => {
        MESSAGING$.notifyError(t('Failed to update vulnerability.'));
      })
      .finally(() => {
        handleCloseEdit();
      });
  };

  useEffect(() => {
    if (!openEdit || !vulnerability?.vulnerability_id) return;

    setLoading(true);
    fetchVulnerability(vulnerability.vulnerability_id)
      .then(res => setFullVulnerability(res.data))
      .catch(() => setFullVulnerability(null))
      .finally(() => setLoading(false));
  }, [openEdit, vulnerability?.vulnerability_id]);

  const entries: PopoverEntry[] = [
    {
      label: t('Update'),
      action: handleOpenEdit,
      userRight: ability.can(ACTIONS.MANAGE, SUBJECTS.PLATFORM_SETTINGS),
    },
    {
      label: t('Delete'),
      action: handleOpenDelete,
      userRight: ability.can(ACTIONS.MANAGE, SUBJECTS.PLATFORM_SETTINGS),
    },
  ];

  const initialValues = fullVulnerability
    ? R.pick([
        'vulnerability_external_id',
        'vulnerability_cvss_v31',
        'vulnerability_description',
        'vulnerability_source_identifier',
        'vulnerability_published',
        'vulnerability_vuln_status',
        'vulnerability_cisa_action_due',
        'vulnerability_cisa_exploit_add',
        'vulnerability_cisa_required_action',
        'vulnerability_cisa_vulnerability_name',
        'vulnerability_cwes',
        'vulnerability_reference_urls',
        'vulnerability_remediation',
      ], fullVulnerability)
    : {};

  return (
    <>
      <ButtonPopover entries={entries} variant="icon" />

      <DialogDelete
        open={openDelete}
        handleClose={handleCloseDelete}
        handleSubmit={handleDelete}
        text={`${t('Do you want to delete this vulnerability:')} ${vulnerability.vulnerability_external_id}?`}
      />

      <Drawer
        open={openEdit}
        handleClose={handleCloseEdit}
        title={t('Update the vulnerability')}
      >
        {loading || !fullVulnerability ? (
          <Loader />
        ) : (
          <VulnerabilityForm
            editing
            initialValues={initialValues}
            onSubmit={handleSubmitEdit}
            handleClose={handleCloseEdit}
          />
        )}
      </Drawer>
    </>
  );
};

export default VulnerabilityPopover;
